/**
 * 实现一个阻塞队列
 */
public class MyBlockingQueue {

    private static MyBlockingQueue myBlockingQueue = new MyBlockingQueue();

    private Integer[] element = new Integer[5];

    private volatile int head = 0;

    private volatile int tail = 0;

    private volatile int size = 0;

    public MyBlockingQueue() {
//        if (capacity <= 0) {
//            throw new RuntimeException("capacity 必须要大于零~");
//        }
//        element = new Integer[5];
    }

    public static MyBlockingQueue getMyBlockingQueue() {
        return myBlockingQueue;
    }

    public void put (Integer value) throws InterruptedException {

        synchronized (this) {
            while (size >= element.length) {
                System.out.println("队列满了~, 阻塞等待");
                this.wait();
            }

            element[tail] = value;
            tail++;
            if (tail >= element.length) {
                tail = 0;
            }
            size++;
            this.notifyAll();
        }
    }

    public Integer take() throws InterruptedException {

        synchronized (this) {
            while (size == 0) {
                System.out.println("队列为空~, 阻塞等待");
                this.wait();
            }
            Integer value = element[head];
            head++;
            if (head >= element.length) {
                head = 0;
            }
            size--;
            this.notifyAll();
            return value;
        }
    }

    public static void main(String[] args) throws InterruptedException {

        Thread thread1 = new Thread(() -> {
            try {
                myBlockingQueue = MyBlockingQueue.getMyBlockingQueue();
                myBlockingQueue.put(1);
                myBlockingQueue.put(2);
                myBlockingQueue.put(3);
                myBlockingQueue.put(4);
                myBlockingQueue.put(5);
                myBlockingQueue.put(6);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        Thread thread2 = new Thread(() -> {
            try {
                myBlockingQueue = MyBlockingQueue.getMyBlockingQueue();
                System.out.println(myBlockingQueue.take());
                System.out.println(myBlockingQueue.take());
                System.out.println(myBlockingQueue.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        thread1.start();
        Thread.sleep(2000);
        thread2.start();
    }
}
